Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize json encoding #2481

Merged

Conversation

philippthun
Copy link
Member

@philippthun philippthun commented Aug 27, 2021

While looking at the performance of the /v3/security_groups endpoints (PR #2475), I also checked how much the database queries were contributing to the overall response times. As this was not much after optimizing the queries, I started to look into the topic of JSON serialization. I found several comments and benchmarks claiming that Oj is the fastest JSON encoder/decoder; so I started with a small PoC.

I've managed to completely switch to Oj and run all unit tests successfully. For comparison of JSON outputs before and after the change, I use the jd command-line tool.

I decided to introduce an optional config property (use_optimized_json_encoder). I've enabled it on a foundation and successfully run CATS.

Here are some results of locally executed performance tests (X-Runtime header):

GET /v3/security_groups?per_page=500 as admin * GET /v3/security_groups/:guid as regular user
baseline 19.802s 0.195s
PR #2255 5.520s 0.158s
PR #2475 3.492s 0.029s
this PR 2.506s 0.025s

* each security group is assigned to 500 spaces

  • I have reviewed the contributing guide

  • I have viewed, signed, and submitted the Contributor License Agreement

  • I have made this pull request to the main branch

  • I have run all the unit tests using bundle exec rake

  • I have run CF Acceptance Tests *

* We cannot run all CATS on our foundations as we do not enable all CF features, but all the executed tests were successful:

Ran 136 of 216 Specs
SUCCESS! -- 136 Passed | 0 Failed | 3 Pending | 77 Skipped

@philippthun philippthun force-pushed the optimize-json-encoding branch 3 times, most recently from 203f4a0 to 0213551 Compare August 27, 2021 13:49
@philippthun philippthun marked this pull request as ready for review September 15, 2021 08:43
@JenGoldstrich
Copy link
Contributor

Hey @philippthun,

Thanks for the PR!

Oj seems actively maintained so that sounds good, one thing I did notice is that this PR introduces another gem rspec-json_expectations which seems to not be actively maintained based on the last commit being from two years ago and this comment from May 2021 attempting to reach out to maintainers. I think we should continue to use .includes json-sub-string or switch to a more actively maintained JSON library.

@philippthun philippthun force-pushed the optimize-json-encoding branch from 0213551 to e5076b3 Compare September 22, 2021 07:25
@philippthun
Copy link
Member Author

Hi @JenGoldstrich! Thanks for your review. The rspec-json_expectations gem is indeed not really needed. I've removed it from the PR and adapted the tests.

@tjvman
Copy link
Contributor

tjvman commented Sep 29, 2021

@philippthun Are you planning to make a PR to capi-release to add the new config property?

@philippthun
Copy link
Member Author

@tjvman I'm not sure about this. Ideally using the optimized json encoder should become the default. It might make sense to add the config option also to CAPI and then enable it on some foundations to see if everything is really compatible. And in the end this option could then be removed again...

@tjvman
Copy link
Contributor

tjvman commented Oct 7, 2021

@philippthun Yeah, that makes sense to me for this kind of performance optimization thing - make it an opt-in at first, then make it the default. How long (time or number of releases) do you think we should leave it as optional

I don't see a way to enable the use_optimized_json_encoder besides editing the config via ssh after deploying, but I might be missing something. Assuming I'm not, then the option should be exposed in capi-release - otherwise it doesn't make sense to have it be a configurable thing (don't want to encourage users to live-edit the CC config)

@philippthun
Copy link
Member Author

@tjvman I've create a CAPI PR (cloudfoundry/capi-release#208) that exposes the use_optimized_json_encoder config property as experimental.

I guess we would enable it stepwise on our foundations, so the property might stay there for a few months.

- Parse JSON response instead of searching for a substring.
- Decode 'X-Broker-Api-Originating-Identity' header value and check
  contained 'user_id' instead of comparing two base64 encoded strings.
- Add missing '}' to JSON string.
- Add 'oj' gem.
- Introduce optional 'use_optimized_json_encoder' config property.
- If 'use_optimized_json_encoder' is true, use Oj (optimized for Rails)
  and omit 'as_json' calls for all Presenters.
@philippthun philippthun force-pushed the optimize-json-encoding branch from e5076b3 to 293c9c2 Compare November 11, 2021 16:52
@Gerg
Copy link
Member

Gerg commented Nov 11, 2021

I think this is a great change and should provide API-wide performance improvements!

@sweinstein22 sweinstein22 merged commit 92ca92f into cloudfoundry:main Nov 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants